package com.me.myFramework.myAop.aop130;

import com.me.myFramework.myAop.IBuy;
import com.me.myFramework.myAop.Switch;
import com.me.myFramework.myAop.aop130.advice.method.AfterReturningAdvice;
import com.me.myFramework.myAop.aop130.advice.method.MethodBeforeAdvice;
import org.springframework.aop.ClassFilter;
import org.springframework.aop.MethodMatcher;
import org.springframework.aop.Pointcut;
import org.springframework.aop.support.NameMatchMethodPointcut;

import java.lang.reflect.Method;

/**
 * 自己实现 AOP-130  <p></p>
 *
 * 把 MethodBeforeAdviceInterceptor 中的 before() 进一步抽离到 advice接口。
 * 把 模板方法 和 用户自定义的增强逻辑彻底分离开，同时需要另外定义一个容器（ProxyFactory）接收 用户定义的增强逻辑、目标对象
 *
 * @author ME
 */
public class MyAop130 {

    public static void main(String[] args) throws Throwable {
        ProxyFactory factory = new ProxyFactory(new Switch());
        Pointcut pointcut = new Pointcut() {
            @Override
            public ClassFilter getClassFilter() {
                return ClassFilter.TRUE;
            }

            @Override
            public MethodMatcher getMethodMatcher() {
                NameMatchMethodPointcut methodPointcut = new NameMatchMethodPointcut();
                methodPointcut.setMappedName("buy");
                return methodPointcut;
            }
        };
        factory.addAdvisor(new DefaultPointcutAdvisor(new BeforeAdvice111(), pointcut));
        factory.addAdvisor(new DefaultPointcutAdvisor(new AfterReturningAdvice222(), Pointcut.TRUE));
        IBuy proxy = (IBuy) factory.getProxy();
        proxy.buy("Tom");

        System.out.println();
        proxy.talk();
    }

    /**
     * 方法前的增强111
     */
    static class BeforeAdvice111 implements MethodBeforeAdvice {
        @Override
        public void before(Method method, Object[] args, Object target) throws Throwable {
            if (isCustomMethod(method.getName())) {
                System.out.println("[AOP1] 就是想记录谁消费了：" + args[0]);
            }
        }
    }

    /**
     * 方法正常返回的增强222
     */
    static class AfterReturningAdvice222 implements AfterReturningAdvice {
        @Override
        public void afterReturning(Object returnValue, Method method, Object[] args, Object target) {
            if (isCustomMethod(method.getName())) {
                if ("Xbox".equals(returnValue)) {
                    System.out.println("[AOP2] 没货了，没买到 Xbox");
                }
                else {
                    System.out.println("[AOP2] 喜提一台 " + returnValue);
                }
            }
        }
    }

    static boolean isCustomMethod(String methodName) {
        return !"toString".equals(methodName) && !"hashCode".equals(methodName) && !"equals".equals(methodName)
                && !"clone".equals(methodName);
    }

}
